<?php

namespace App\HttpController;


use App\Common\Log;
use App\Common\Web\TempView;
use App\Traits\TraitCommon;
use App\Traits\TraitConnectDB;
use EasySwoole\Http\AbstractInterface\Controller;
use EasySwoole\Http\Session\SessionDriver;
use XWX\Common\H;
use XWX\Common\XReturn;


class ControllerBase extends Controller
{
    use TraitConnectDB, TraitCommon;


    protected function onRequest(?string $action): ?bool
    {
        Log::funcLogInfo(__METHOD__, "Controller[BEGIN]");

        $this->response()->withHeader('Access-Control-Allow-Origin', '*');


        $this->funcGetWebIP();
        $this->funcGetX();


        return true;
    }


    protected function onException(\Throwable $throwable): void
    {
        $app = new TempView('/error/500.html');

        $errmsg = "{$throwable->getMessage()} at file:{$throwable->getFile()} line:{$throwable->getLine()}";
        $file = "file:{$throwable->getFile()} line:{$throwable->getLine()}";
        Log::funcLogErr(__METHOD__, $errmsg);

        $app->funcSetReplace([
            '{getMessage}' => $throwable->getMessage(),
            '{getTraceAsString}' => $throwable->getTraceAsString(),
            '{file}' => $file,
        ]);

        $r = $app->funcPageContent();

        $this->response()->withStatus(500);
        $this->response()->write($r->getData('page_content'));
    }


    /**
     * @return XReturn
     * @throws \Exception
     */
    protected function commonR()
    {
        $key = 'common_return';

        $r = $this->context()->get($key);
        if (!isset($r))
        {
            $r = $this->funcGetR(0);
            $this->context()->set($key, $r);
        }

        return $r;
    }


    protected function reqParam($key = null)
    {
        $val = null;
        if (H::funcStrHasAnyText($key))
        {
            $val = $this->request()->getRequestParam($key);
        }
        else
        {
            $val = $this->request()->getRequestParam();
        }


        return $val;
    }


    private function xsession_key()
    {
        return 'XSESSION';
    }

    protected function xsession(): SessionDriver
    {
        $key = $this->xsession_key();

        $session = $this->context()->get($key);
        if (!isset($session))
        {
            $handler = new \App\Common\SessionHandlerRedis();

            $session = $this->session($handler);
            $session->name($key);
            $session->start();

            $this->context()->set($key, $session);
        }


        return $session;
    }


    function index()
    {
        throw new \Exception('NOT_FOUND');
    }


    protected function afterAction(?string $actionName): void
    {
        //释放session
        $session = $this->context()->get($this->xsession_key());
        if (isset($session))
        {
            $session->writeClose();
        }

        $this->context()->destroy();


        Log::funcLogInfo(__METHOD__, "Controller[END]");
    }


    /**
     * 获取IP
     *
     * @return string
     * @throws \Exception
     */
    public function funcGetWebIP()
    {
        $ip = $this->context()->funcGetWebIP();
        if (H::funcStrHasAnyText($ip))
        {
            return $ip;
        }

        //header 地址，例如经过nginx proxy后
        $headers = $this->request()->getHeaders();
        $ips = H::funcArrayGet($headers, "x-real-ip");

        $ip = '';
        if ($ips != null && count($ips) > 0)
        {
            $ip = $ips[0];
        }

        if (H::funcStrIsNullOrEmpty($ip))
        {
            $client_info = \EasySwoole\EasySwoole\ServerManager::getInstance()
                ->getSwooleServer()
                ->getClientInfo($this->request()->getSwooleRequest()->fd);

            $ip = $client_info['remote_ip'];
        }

        $this->context()->set('ip', $ip);

        return $ip;
    }

    /**
     * 当前页面URL
     *
     * @return string
     * @throws \Exception
     */
    public function funcGetWebUrl()
    {
        $url = null;

        return $url;
    }


    /**
     * user-agent
     *
     * @return string
     */
    public function funcGetUserAgent()
    {
        return $this->funcGetHeader("user-agent");
    }

    /**
     * 获取请求头信息
     *
     * @param $name
     * @return string
     */
    public function funcGetHeader($name)
    {
        $val = $this->request()->getHeader($name);

        $string1 = '';
        if (is_array($val))
        {
            $string1 = implode('', $val);
        }
        else
        {
            $string1 = $val;
        }

        return $string1;
    }


    /**
     * 返回错误
     *
     * @param $errcode
     * @param $errmsg
     * @param null $data
     * @throws \Exception
     */
    public function funcWriteErr($errcode, $errmsg, $data = null)
    {
        $r = $this->commonR();

        $r->errcode = $errcode;
        $r->errmsg = $errmsg;
        $r->setData('data', $data);

        $this->funcWriteCommonR();
    }

    /**
     * 返回错误
     *
     * @param $errcode
     * @param $errmsg
     * @param null $data
     * @throws \Exception
     */
    public function funcWriteErrR(XReturn $r)
    {
        $common_r = $this->commonR();
        $common_r->errcode = $r->errcode;
        $common_r->errmsg = $r->errmsg;
        $common_r->setVal('data', $r->getData());

        $this->funcWriteCommonR();
    }

    /**
     * 返回json，想请求中断，请在函数前面加return
     */
    public function funcWriteCommonR()
    {
        if (!$this->response()->isEndResponse())
        {
            $r = $this->commonR();
            if ($r->err())
            {
                Log::funcLogErr(__METHOD__, H::funcToStr($r));
            }

            $this->response()->withHeader("Content-type", "application/json;charset=utf-8");
            $this->response()->write(H::funcToStr($r));
            $this->response()->end();
        }
    }


    /**
     * 请求参数验证，错误码422
     *
     * @param XReturn[] $errors
     * @param null $errmsg 自定义提示
     * @throws \Exception
     */
    protected function funcWriteValidate($errors, $errmsg = null)
    {
        $this->response()->withStatus(422);

        $data = [
            'errors' => $errors,
        ];


        if (H::funcStrIsNullOrEmpty($errmsg))
        {
            $errmsg = '表单验证失败';
        }

        $this->funcWriteErr(422, $errmsg, $data);
    }


    /**
     * 视图
     *
     * @param $view *view路径
     * @param $replace_data *页面参数
     */
    protected function funcReturnView($view, array $replace_data = [])
    {
        $app = new TempView($view);


        if (count($replace_data) > 0)
        {
            $app->funcSetReplace($replace_data);
        }

        $r = $app->funcPageContent();

        $this->response()->write($r->getData('page_content'));
    }


    /**
     * 返回系统提示
     *
     * @param $title
     * @param $desc
     * @param null $icon
     *
     * 图标样式
     * weui-icon-info
     * weui-icon-warn
     * weui-icon-success
     */
    protected function funcReturnViewSysInfo($title, $desc, $icon = 'weui-icon-info')
    {
        $data = [
            '{icon}' => $icon,
            '{title}' => $title,
            '{desc}' => $desc,
        ];

        $this->funcReturnView('/error/sys_info.html', $data);
    }


    /**
     * 当前第几页
     *
     * @return int
     */
    function funcGetPageIndex()
    {
        $page_index = $this->reqParam('page_index');
        $page_index = intval($page_index);
        if ($page_index <= 0)
        {
            $page_index = 1;
        }

        return $page_index;
    }

    /**
     * 1页显示多少条数据
     *
     * @return int
     */
    function funcGetPageSize()
    {
        $page_size = $this->reqParam('page_size');
        $page_size = intval($page_size);
        if ($page_size <= 0)
        {
            $page_size = 10;
        }

        return $page_size;
    }

    function funcGetPageIndexXPage()
    {
        $page_index = $this->funcGetPageIndex();
        $page_size = $this->funcGetPageSize();

        return ($page_index - 1) * $page_size;
    }


    /**
     * 是否微信环境
     *
     * @return bool
     */
    function funcEnvIsWeixin()
    {
        $user_agent = $this->funcGetUserAgent();
        if (H::funcStrContains($user_agent, 'MicroMessenger'))
        {
            return true;
        }

        return false;
    }

    /**
     * 是否支付宝环境
     *
     * @return bool
     */
    function funcEnvIsAlipay()
    {
        $user_agent = $this->funcGetUserAgent();
        if (H::funcStrContains($user_agent, 'Alipay'))
        {
            return true;
        }

        return false;
    }
}